﻿#include "GenerateAudioFile.h"
#include "TextSpeak.h"
#include "AudioFile.h"

GenerateAudioFile::GenerateAudioFile(TextSpeak *speak, const QString &content, qint64 loop) :
    content_(content), index_(0), speakItem_(speak), stackCount_(0)
{
    this->setProperty("loop", loop);
    this->start();
    this->moveToThread(this);
}

GenerateAudioFile::~GenerateAudioFile()
{
    qDebug() << __FUNCTION__;
    this->exit();
    this->wait();
}

void GenerateAudioFile::init(int speed, int volume, const QString &profile, const QString &fileName)
{
    QEventLoop loop;

    speed_ = speed;
    volume_ = volume;
    profile_ = profile;
    fileName_ = fileName;
    loop_ = &loop;

    QTimer::singleShot(10, this, SLOT(onDelayInit()));
    loop.exec();
}

void GenerateAudioFile::release()
{
    QEventLoop loop;
    connect(this, SIGNAL(finished()), &loop, SLOT(quit()));
    QMetaObject::invokeMethod(this, "onRelease", Qt::QueuedConnection);
    loop.exec();
}

void GenerateAudioFile::onInit(QEventLoop *loop, int speed, int volume, const QString &profile, const QString &fileName)
{
    speakItem_->setRate(speed);
    speakItem_->setVolume(volume);
    speakItem_->setVoice(profile);

    audioFile_ = QSharedPointer<AudioFile>(new AudioFile(fileName));
    dateTime_ = QDateTime::currentDateTime();

    connect(speakItem_, SIGNAL(doSpeakBuffer(QByteArray,QString)), this, SLOT(onSpeakBuffer(QByteArray)), Qt::QueuedConnection);

    QTimer::singleShot(0, this, SLOT(onNext()));
    QTimer::singleShot(0, loop, SLOT(quit()));
}

void GenerateAudioFile::onRelease()
{
    qDebug() << __FUNCTION__;
    if (audioFile_) {
        audioFile_->finished();
        audioFile_.clear();
    }
    if (stackCount_ > 0) {
        //再次放入队列中. 等待之前的队列执行完成
        QTimer::singleShot(0, this, SLOT(onRelease()));
        return;
    }

    qApp->removePostedEvents(this);
    speakItem_->disconnect(this);
    this->exit();
}

void GenerateAudioFile::onNext()
{
    qDebug() << __FUNCTION__;
    QString line = this->popLine();
    if (line.isNull()) {
        emit doSpeakProgress(index_);
        return;
    }
    stackCount_ ++;
    speakItem_->speak(line);
}

void GenerateAudioFile::onDelayInit()
{
    qDebug() << __FUNCTION__;
    this->onInit(loop_, speed_, volume_, profile_, fileName_);
}

void GenerateAudioFile::onSpeakBuffer(const QByteArray &data)
{
    stackCount_--;

    if (!audioFile_)
        return;

    audioFile_->write(data);

    if (dateTime_.msecsTo(QDateTime::currentDateTime()) >= 1000) {
        emit doSpeakProgress(index_);
        dateTime_ = QDateTime::currentDateTime();
    }

    QTimer::singleShot(0, this, SLOT(onNext()));
}


QString GenerateAudioFile::popLine()
{
    int indexStart = index_;
    if (index_ >= content_.length())
        return QString();

    QRegExp regexp("\\W");
    regexp.setMinimal(true);
    index_ = regexp.indexIn(content_, index_);
    if (index_ == -1) {
        if (indexStart >= content_.length()) {
            return QString();
        } else {
            index_  = content_.length();
            return content_.mid(indexStart);
        }
    }
    index_ += regexp.matchedLength();
    QString text = content_.mid(indexStart, index_ - indexStart);
    return text.trimmed();
}
